home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 1.iso
/
DEMON
/
RISCOS2
/
TCP_131S.ARC
/
c
/
icmpcmd
< prev
next >
Wrap
Text File
|
1994-03-12
|
11KB
|
503 lines
/* ICMP-related user commands */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "global.h"
#include "mbuf.h"
#include "cmdparse.h"
#include "domain.h"
#include "netuser.h"
#include "internet.h"
#include "timer.h"
#include "ping.h"
#include "misc.h"
#include "Terminal.h"
#include "udp.h"
#include "icmp.h"
#define HOPMAXQUERY 5 /* Max# queries each TTL value */
extern int16 lport; /* local port placeholder */
static int pingem(int32, int16, int16);
static int16 hash_ping(int32);
static struct ping *add_ping(int32);
static void del_ping(struct ping *);
static void send_hop(void);
static int docheck (int argc,char *argv[]);
static int dottl (int argc,char *argv[]);
static int dowait (int argc,char *argv[]);
static int donum (int argc,char *argv[]);
struct cmds Hopcmds[] = {
"check", docheck, 2, "hop check <host>", NULLCHAR,
"maxttl", dottl, 0, 0, NULLCHAR,
"maxwait", dowait, 0, 0, NULLCHAR,
"queries", donum, 0, 0, NULLCHAR,
NULLCHAR,
};
/* ICMP message types */
extern char *icmptypes[];
/* ICMP unreachable messages */
extern char *unreach[];
int dohop(int argc, char *argv[])
{
return subcmd(Hopcmds, argc, argv);
}
int doicmpstat(void)
{
extern struct icmp_errors icmp_errors;
extern struct icmp_stats icmp_stats;
extern char *icmptypes[];
register int i;
cwprintf(NULL, "ICMP: chksum err %u no space %u icmp %u bdcsts %u\r\n",
icmp_errors.checksum,icmp_errors.nospace,icmp_errors.noloop,
icmp_errors.bdcsts);
cwprintf(NULL, "type rcvd sent\r\n");
for(i=0;i<ICMP_TYPES;i++)
{
if(icmp_stats.input[i] == 0 && icmp_stats.output[i] == 0)
continue;
cwprintf(NULL, "%-6u%-6u%-6u",i,icmp_stats.input[i],
icmp_stats.output[i]);
if(icmptypes[i] != NULLCHAR)
cwprintf(NULL, " %s",icmptypes[i]);
cwprintf(NULL, "\r\n");
}
return 0;
}
/* Hash table list heads */
struct ping *ping[PMOD];
/* Counter for generating seq numbers */
static int16 iclk;
/* Increment counter -- called by low level clock tick */
void icmpclk(void)
{
iclk++;
}
static int32 cticks;
static int16 hopttl;
static int16 hopquery;
static struct socket lsocket, fsocket; /* socket address */
static int32 lastsource;
static int32 hopmean;
static struct timer hop_time_t;
static Terminal *window;
static int16 Hopmaxttl = 30; /* max attempts */
static int16 Hopmaxwait = 5; /* secs timeout each attempt */
static int16 Hopmaxquery = 3; /* #probes each attempt */
/* Set/show # queries sent each TTL value */
static int donum(int argc, char *argv[])
{
int n = atoi(argv[1]);
if (argc < 2)
{
cwprintf(NULL, "%d checks for each host\n", Hopmaxquery);
}
else if (n < 1 || n > HOPMAXQUERY)
{
cwprintf(NULL, "Checks for each host must be > 0 and <= %d\n", HOPMAXQUERY);
return (1);
}
else
{
Hopmaxquery = n;
}
return (0);
}
/* Set/show maximum TTL value for a traceroute query */
static int dottl(int argc, char *argv[])
{
int n = atoi(argv[1]);
if (argc < 2)
{
cwprintf(NULL, "Maximum ttl %d\n", Hopmaxttl);
}
else if (n < 2 || n > 255)
{
cwprintf(NULL, "Maximum ttl must be > 0 and <= 255\n");
return (1);
}
else
{
Hopmaxttl = n;
}
return (0);
}
static void hop_timeout(void *vp)
{
if (hopquery == 1)
{
if (lastsource != 0)
{
cwprintf(window, " (mean %ld)", 10 * hopmean / Hopmaxquery);
hopmean = 0;
}
cwprintf(window, "\n%3d %-18s", hopttl, inet_ntoa(0));
}
cticks = clock() - cticks;
cwprintf(window, " *** ");
hopmean += cticks;
send_hop();
}
/* Set/show #secs until timeout for a traceroute query */
static int dowait(int argc, char *argv[])
{
int n = atoi(argv[1]);
if (argc < 2)
{
cwprintf(NULL, "Maximum wait for reply %d\n", Hopmaxwait);
}
else if (n < 1)
{
cwprintf(NULL, "Maximum wait for reply must be > 0\n");
return (1);
}
else
{
Hopmaxwait = n;
}
return (0);
}
static void send_hop(void)
{
if (hopquery >= Hopmaxquery)
{
hopquery = 0;
hopttl++;
}
if (hopttl < Hopmaxttl)
{
send_udp(&lsocket, &fsocket, 0, hopttl, 0, 0, 0, 0);
cticks = clock();
hopquery++;
hop_time_t.func = hop_timeout; /* what to call on timeout */
hop_time_t.arg = NULL;
set_timer(&hop_time_t, Hopmaxwait * 1000L);
start_timer(&hop_time_t);
}
}
void hop_rec(struct icmp *icmphdr, struct udp *udphdr, int32 source, int16 type)
{
BOOL tracedone = FALSE;
struct socket fsocket; /* socket address */
if (udphdr->source != lsocket.port)
return;
stop_timer(&hop_time_t);
if (lastsource != source)
{
if (lastsource != 0)
{
cwprintf(window, " (mean %ldms)", 10 * hopmean / Hopmaxquery);
hopmean = 0;
}
cwprintf(window, "\n%3d %-15s", hopttl, inet_ntoa(source));
}
lastsource = source;
cticks = clock() - cticks;
cwprintf(window, " %4ldms", 10 * cticks);
hopmean += cticks;
if (icmphdr->type == DEST_UNREACH)
{
switch(icmphdr->code)
{
case PORT_UNREACH:
++tracedone;
break;
case NET_UNREACH:
++tracedone;
cwprintf(window, " !N");
break;
case HOST_UNREACH:
++tracedone;
cwprintf(window, " !H");
break;
case PROT_UNREACH:
++tracedone;
cwprintf(window, " !P");
break;
case FRAG_NEEDED:
++tracedone;
cwprintf(window, " !F");
break;
case ROUTE_FAIL:
++tracedone;
cwprintf(window, " !S");
break;
case ADMIN_PROHIB:
++tracedone;
cwprintf(window, " !A");
break;
default:
cwprintf(window, " !?");
break;
}
}
if (!tracedone)
send_hop();
if (tracedone || hopttl >= Hopmaxttl)
{
cwprintf(window, "\n\ntraceroute done: ");
if (hopttl >= Hopmaxttl)
{
cwprintf(window, "!! maximum TTL exceeded\n");
}
else if (source == fsocket.address && icmphdr->code == DEST_UNREACH)
{
cwprintf(window, "normal (%s %s)\n", icmptypes[type], unreach[icmphdr->code]);
}
else
{
cwprintf(window, "!! %s %s\n", icmptypes[type], unreach[icmphdr->code]);
}
window->Attr = ATTR_REVERSE;
window->Flags.flags.dont_destroy = FALSE;
cwprintf(window, "\nThis session has finished, please close the window\n");
window = NULL;
}
}
static int docheck(int argc, char *argv[])
{
char title[80];
/* Set up the connection. */
fsocket.address = resolve(argv[1]);
if (fsocket.address != 0)
{
fsocket.port = (int16) (32768L+666);
lsocket.address = ip_addr; /* our ip address */
lsocket.port = lport++; /* next unused port */
hopttl = 0;
hopquery = Hopmaxquery;
lastsource = 0;
hopmean = 0;
sprintf(title, "Hop check to %s", argv[1]);
window = Window_Open(NULL, title, term_NO_INPUT);
send_hop();
}
else
{
cwprintf(NULL, "Hop - Can't resolve %s\n", argv[1]);
}
return(0);
}
/* Send ICMP Echo Request packets */
int doping(int argc, char **argv)
{
int32 dest;
struct ping *pp1;
register struct ping *pp;
int16 hval;
int i;
if(argc < 2)
{
cwprintf(NULL, "Host Sent Rcvd %% Avg RTT Interval\r\n");
for (i = 0; i < PMOD; i++)
{
for (pp = ping[i]; pp != NULLPING; pp = pp->next)
{
cwprintf(NULL, "%-16s",inet_ntoa(pp->remote));
cwprintf(NULL, "%8lu%8lu", pp->count, pp->echoes);
cwprintf(NULL, "%4lu%10lu%10lu\r\n",
(long)pp->echoes * 100 / pp->count,
pp->echoes != 0 ?
(long)pp->ttotal * MSPTICK / pp->echoes : 0,
((long)pp->timer.start * MSPTICK + 500) / 1000);
}
}
return 0;
}
if (strcmp(argv[1],"clear") == 0)
{
for(i = 0; i < PMOD; i++)
{
for (pp = ping[i]; pp != NULLPING; pp = pp1)
{
pp1 = pp->next;
del_ping(pp);
}
}
return 0;
}
if ((dest = resolve(argv[1])) == 0)
{
cwprintf(NULL, "Host %s unknown\r\n",argv[1]);
return 1;
}
/* See if dest is already in table */
hval = hash_ping(dest);
for (pp = ping[hval]; pp != NULLPING; pp = pp->next)
{
if(pp->remote == dest)
{
break;
}
}
if(argc > 2)
{
/* Inter-ping time is specified; set up timer structure */
if(pp == NULLPING)
pp = add_ping(dest);
if (pp->window != NULL)
cwtitle(pp->window, "Ping - %s", argv[1]);
pp->timer.start = atoi(argv[2]) * (int32)(1000 / MSPTICK);
pp->timer.func = ptimeout;
pp->timer.arg = (char *)pp;
pp->remote = dest;
start_timer(&pp->timer);
pp->count++;
pingem(dest, iclk, REPEAT);
}
else
pingem(dest, iclk, ONESHOT);
return 0;
}
/* Called by ping timeout */
void ptimeout(char *p)
{
register struct ping *pp;
/* Send another ping */
pp = (struct ping *)p;
pp->count++;
pingem(pp->remote,iclk,REPEAT);
start_timer(&pp->timer);
}
/* Send ICMP Echo Request packet */
static int pingem(int32 dest, int16 seq, int16 id)
{
struct mbuf *bp;
struct icmp icmp;
extern struct icmp_stats icmp_stats;
icmp_stats.output[ECHO]++;
icmp.type = ECHO;
icmp.code = 0;
icmp.args.echo.seq = seq;
icmp.args.echo.id = id;
if((bp = htonicmp(&icmp,NULLBUF)) == NULLBUF)
return 0;
return ip_send(ip_addr,dest,ICMP_PTCL,0,0,bp,len_mbuf(bp),0,0);
}
/* Called with incoming Echo Reply packet */
void echo_proc(int32 source, int32 dest, struct icmp *icmp)
{
register struct ping *pp;
int16 hval;
int16 rtt;
dest = dest;
rtt = iclk - icmp->args.echo.seq;
hval = hash_ping(source);
for(pp = ping[hval]; pp != NULLPING; pp = pp->next)
if(pp->remote == source)
break;
if (pp == NULLPING || icmp->args.echo.id != 1)
{
cwprintf(NULL, "%s: echo reply id %u seq %u, %lu ms\r\n",
inet_ntoa(source),
icmp->args.echo.id,icmp->args.echo.seq,
(long)rtt * MSPTICK);
}
else if (pp->window != NULL)
{
cwprintf(pp->window, "echo reply id %u seq %u, %lu ms\r\n",
icmp->args.echo.id,icmp->args.echo.seq,
(long)rtt * MSPTICK);
}
else
{
/* Repeated poll, just keep stats */
pp->ttotal += rtt;
pp->echoes++;
}
}
static int16 hash_ping(int32 dest)
{
int16 hval;
hval = (hiword(dest) ^ loword(dest)) % PMOD;
return hval;
}
/* Add entry to ping table */
static struct ping * add_ping(int32 dest)
{
struct ping *pp;
int16 hval;
pp = (struct ping *)calloc(1,sizeof(struct ping));
if(pp == NULLPING)
return NULLPING;
hval = hash_ping(dest);
pp->prev = NULLPING;
pp->next = ping[hval];
if(pp->next != NULLPING)
pp->next->prev = pp;
ping[hval] = pp;
pp->window = Window_Open(NULL, "Ping", term_NO_INPUT);
return pp;
}
/* Delete entry from ping table */
static void del_ping(struct ping *pp)
{
int16 hval;
stop_timer(&pp->timer);
if(pp->next != NULLPING)
pp->next->prev = pp->prev;
if(pp->prev != NULLPING)
{
pp->prev->next = pp->next;
}
else
{
hval = hash_ping(pp->remote);
ping[hval] = pp->next;
}
if (pp->window)
{
pp->window->Attr = ATTR_REVERSE;
pp->window->Flags.flags.dont_destroy = FALSE;
cwprintf(pp->window, "\nThis session has finished, please close the window\n");
}
free((char *)pp);
}